{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> 原文地址 [www.cnblogs.com](https://www.cnblogs.com/xleng/p/11791944.html)\n",
    "\n",
    "# 摘要\n",
    "\n",
    "\n",
    "　　GStreamer 提供了不同的命令行工具用于快速的查看信息以及验证 Pipeline 的是否能够正确运行，在平时的开发过程中，我们也优先使用 GStreamer 的命令行工具验证，再将 Pipeline 集成到应用中。本文将介绍 gst-inspect-1.0，gst-discoverer-1.0，gst-launch-1.0 命令行工具的使用。\n",
    "\n",
    "# gst-inspect-1.0\n",
    "\n",
    "此命令有 3 种工作模式，实际中我们常用第一种和第三种方式：\n",
    "\n",
    "## 1. 不带任何参数\n",
    "\n",
    "这样会列出当前系统中支持的所有 Element，这些 Element 可用于构造 Pipeline.\n",
    "\n",
    "## 2. 跟文件名\n",
    "\n",
    "这样会将指定文件作为一个 GStreamer 插件，尝试列出其中所包含的 Element。例如下面的命令列出了 libgstjpeg.so 所包含的 2 个 Elements：\n",
    "\n",
    "```sh\n",
    "$ gst-inspect-1.0 /usr/lib/x86\\_64-linux-gnu/gstreamer-1.0/libgstjpeg.so\n",
    "Plugin Details:\n",
    "  Name                     jpeg\n",
    "  Description              JPeg plugin library\n",
    "  Filename                 /usr/lib/x86\\_64-linux-gnu/gstreamer-1.0/libgstjpeg.so\n",
    "  Version                  1.8.3\n",
    "  License                  LGPL\n",
    "  Source module            gst-plugins-good\n",
    "  Source release date      2016-08-19\n",
    "  Binary package           GStreamer Good Plugins (Ubuntu)\n",
    "  Origin URL               https://launchpad.net/distros/ubuntu/+source/gst-plugins-good1.0\n",
    "\n",
    "  jpegenc: JPEG image encoder\n",
    "  jpegdec: JPEG image decoder\n",
    "\n",
    "  2 features:\n",
    "  +-- 2 elements\n",
    "```\n",
    "\n",
    "## 3. 跟 Element 名\n",
    "\n",
    "会列出 Element 的详细信息。例如，下面的命令会列出 jpeg 解码器所支持的输入数据类型，Pad 信息，支持的属性及值。我们主要关注 Pad Template，以及 Element 的属性信息。\n",
    "\n",
    "```sh\n",
    "$ gst-inspect-1.0 jpegdec\n",
    "Factory Details:\n",
    "  Rank                     primary (256)\n",
    "  Long-name                JPEG image decoder\n",
    "  Klass                    Codec/Decoder/Image\n",
    "  Description              Decode images from JPEG format\n",
    "  Author                   Wim Taymans <wim@fluendo.com>\n",
    "\n",
    "Plugin Details:\n",
    "  Name                     jpeg\n",
    "  Description              JPeg plugin library\n",
    "  Filename                 /usr/lib/x86\\_64-linux-gnu/gstreamer-1.0/libgstjpeg.so\n",
    "  Version                  1.8.3\n",
    "  License                  LGPL\n",
    "  Source module            gst-plugins-good\n",
    "  Source release date      2016-08-19\n",
    "  Binary package           GStreamer Good Plugins (Ubuntu)\n",
    "  Origin URL               https://launchpad.net/distros/ubuntu/+source/gst-plugins-good1.0\n",
    "\n",
    "GObject\n",
    " +----GInitiallyUnowned\n",
    "       +----GstObject\n",
    "             +----GstElement\n",
    "                   +----GstVideoDecoder\n",
    "                         +----GstJpegDec\n",
    "\n",
    "Pad Templates:\n",
    "  SINK template: 'sink'\n",
    "    Availability: Always\n",
    "    Capabilities:\n",
    "      image/jpeg\n",
    "\n",
    "  SRC template: 'src'\n",
    "    Availability: Always\n",
    "    Capabilities:\n",
    "      video/x-raw\n",
    "                 format: { I420, RGB, BGR, RGBx, xRGB, BGRx, xBGR, GRAY8 }\n",
    "                  width: \\[ 1, 2147483647 \\]\n",
    "                 height: \\[ 1, 2147483647 \\]\n",
    "              framerate: \\[ 0/1, 2147483647/1 \\]\n",
    "\n",
    "\n",
    "Element Flags:\n",
    "  no flags set\n",
    "\n",
    "Element Implementation:\n",
    "  Has change\\_state() function: gst\\_video\\_decoder\\_change\\_state\n",
    "\n",
    "Element has no clocking capabilities.\n",
    "Element has no indexing capabilities.\n",
    "Element has no URI handling capabilities.\n",
    "\n",
    "Pads:\n",
    "  SINK: 'sink'\n",
    "    Implementation:\n",
    "      Has chainfunc(): gst\\_video\\_decoder\\_chain\n",
    "      Has custom eventfunc(): gst\\_video\\_decoder\\_sink\\_event\n",
    "      Has custom queryfunc(): gst\\_video\\_decoder\\_sink\\_query\n",
    "      Has custom iterintlinkfunc(): gst\\_pad\\_iterate\\_internal\\_links\\_default\n",
    "    Pad Template: 'sink'\n",
    "  SRC: 'src'\n",
    "    Implementation:\n",
    "      Has custom eventfunc(): gst\\_video\\_decoder\\_src\\_event\n",
    "      Has custom queryfunc(): gst\\_video\\_decoder\\_src\\_query\n",
    "      Has custom iterintlinkfunc(): gst\\_pad\\_iterate\\_internal\\_links\\_default\n",
    "    Pad Template: 'src'\n",
    "\n",
    "Element Properties:\n",
    "  name                : The name of the object\n",
    "                        flags: readable, writable\n",
    "                        String. Default: \"jpegdec0\"\n",
    "  parent              : The parent of the object\n",
    "                        flags: readable, writable\n",
    "                        Object of type \"GstObject\"\n",
    "  idct-method         : The IDCT algorithm to use\n",
    "                        flags: readable, writable\n",
    "                        Enum \"GstIDCTMethod\" Default: 1, \"ifast\"\n",
    "                           (0): islow            - Slow but accurate integer algorithm\n",
    "                           (1): ifast            - Faster, less accurate integer method\n",
    "                           (2): float            - Floating-point: accurate, fast on fast HW\n",
    "  max-errors          : (Deprecated) Error out after receiving N consecutive decoding errors (-1 = never fail, 0 = automatic, 1 = fail on first error)\n",
    "                        flags: readable, writable, 0x80000000\n",
    "                        Integer. Range: -1 - 2147483647 Default: 0\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# gst-discoverer-1.0\n",
    "\n",
    "　　此命令在 [GStreamer 基础教程 06 - 获取媒体信息](https://www.cnblogs.com/xleng/p/11277397.html)中使用过，是对 [GstDiscoverer](https://gstreamer.freedesktop.org/documentation/pbutils/gstdiscoverer.html?gi-language=c) 接口的封装，可以方便的查看媒体文件的编码，帧率等信息。\n",
    "\n",
    "\n",
    "```sh\n",
    "$ gst-discoverer-1.0 sintel\\_trailer-480p.mp4\n",
    "Analyzing file:///home/xleng/video/sintel\\_trailer-480p.mp4\n",
    "Done discovering file:///home/xleng/video/sintel\\_trailer-480p.mp4\n",
    "\n",
    "Topology:\n",
    "  container: Quicktime\n",
    "    audio: MPEG-4 AAC\n",
    "    video: H.264 (High Profile)\n",
    "\n",
    "Properties:\n",
    "  Duration: 0:00:52.209000000\n",
    "  Seekable: yes\n",
    "  Live: no\n",
    "  Tags:\n",
    "      audio codec: MPEG-4 AAC audio\n",
    "      maximum bitrate: 128000\n",
    "      datetime: 1970-01-01T00:00:00Z\n",
    "      title: Sintel Trailer\n",
    "      artist: Durian Open Movie Team\n",
    "      copyright: (c) copyright Blender Foundation | durian.blender.org\n",
    "      description: Trailer for the Sintel open movie project\n",
    "      encoder: Lavf52.62.0\n",
    "      container format: ISO MP4/M4A\n",
    "      video codec: H.264 / AVC\n",
    "      bitrate: 535929\n",
    "\n",
    "```\n",
    "\n",
    "# gst-launch-1.0\n",
    "\n",
    "　　gst-launch 是我们平时使用最多的一个命令，它接收一个用字符串方式描述的 Pipline，将其实例化并运行。我们可以用此命令快速的检查 Pipeline 中各个元素是否能够正确的连接起来。当我们需要构建的 Pipeline 很复杂时，我们也可以将 Pipeline 进行拆分，逐步通过 gst-launch 验证 Pipeline 的合法性。  \n",
    "　　通过 gst-launch 验证的字符串 Pipeline 可以直接使用 gst\\_parse\\_launch() 接口将其转化为 GstPipeline 对象，节省了我们单独调用 API 去创建 Element 的时间。  \n",
    "　　当我们用字符串描述 Pipeline 时，每个 Element 之间需要通过叹号 “!\" 分隔 Element，这样 gst-launch 才能正确识别。  \n",
    "　　在使用 gst-launch 时，根据不同的应用场景，我们可以分为以下的类型。\n",
    "\n",
    "采用默认的参数创建 Pipeline\n",
    "------------------\n",
    "\n",
    "　　这种方式我们只需将所使用的 Element 使用叹号分隔即可，例如：\n",
    "\n",
    "```sh\n",
    "$ gst-launch-1.0 videotestsrc ! videoconvert ! autovideosink\n",
    "```\n",
    "\n",
    "# 设置 Element 的属性\n",
    "\n",
    "　　在某些情况下，我们需要修改 Element 的属性, 或指定所需参数（例如 playbin 的 uri 参数），Element 的属性直接跟在 Element 之后。下面的命令会设置 videotestsrc 的视频模式，输出图像为环形。属性支持的值可以通过 gst-inspect 命令查看。\n",
    "\n",
    "```sh\n",
    "$ gst-launch-1.0 videotestsrc pattern=11 ! videoconvert ! autovideosink\n",
    "```\n",
    "\n",
    "　　如果属性值中包含空格，我们可以将其置于单引号或双引号中。\n",
    "\n",
    "```sh\n",
    "$ gst-launch-1.0 -v videotestsrc ! clockoverlay halignment=right valignment=bottom text=\"Edge City\" shaded-background=true font-desc=\"Sans, 36\" ! videoconvert ! autovideosink\n",
    "\n",
    "```\n",
    "\n",
    "# 包含分支的 Pipeline\n",
    "\n",
    "　　每个 Element 都有 name 的属性，我们可以利用 name 来实现包含多个分支的复杂的 Pipeline，这常见于有多个输出 / 输入的 Element（mux，demux，tee 等）。  \n",
    "　　下面的命令通过 tee 创建了 2 个分支，分别用于不同的 sink，在一个分支是 Pipeline 完成后（到达 sink），我们可以使用 “name 加一个点号” 重新创建一个分支。\n",
    "\n",
    "```sh\n",
    "$ gst-launch-1.0 videotestsrc ! videoconvert ! tee name=t ! queue ! autovideosink t. ! queue ! autovideosink\n",
    "```\n",
    "\n",
    "　　使用同样的方式，我们也可以将多个分支合并为一个。下面的命令首先解码文件，将视频编码为 H.264，音频编码为 MP3，最终再合并生成 TS 文件。注意 dmux 和 mux Element 的使用。\n",
    "\n",
    "```sh\n",
    "$ gst-launch-1.0 filesrc location=surround.mp4 ! decodebin name=dmux ! queue ! audioconvert ! lamemp3enc ! mux. \\\\\n",
    "```\n",
    "\n",
    "```sh\n",
    "dmux. ! queue ! x264enc ! mpegtsmux name=mux ! queue ! filesink location=out.ts\n",
    "```\n",
    "\n",
    "# 指定 Element 的 Pad\n",
    "\n",
    "　　某些情况下，我们希望自己指定某个 Pad 用于连接，我们可以指定已命名 Element 的 Pad 来实现。\n",
    "\n",
    "```sh\n",
    "$ gst-launch-1.0 souphttpsrc location=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel\\_trailer-480p.webm ! \\\\\n",
    "matroskademux name=d d.video\\_00 ! matroskamux ! filesink location=sintel\\_video.mkv\n",
    "```\n",
    "\n",
    "　　上面的命令会将 sintel\\_trailer-480p.webm 文件进行 Demux，只选择其中的视频 (video\\_00)，再将其保留为 mk 文件，只保留了视频部分。如果想只保留音频部分，可以使用如下命令：\n",
    "\n",
    "```sh\n",
    "$ gst-launch-1.0 souphttpsrc location=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel\\_trailer-480p.webm ! \\\\\n",
    "matroskademux name=d d.audio\\_00 ! vorbisparse ! matroskamux ! filesink location=sintel\\_audio.mka\n",
    "```\n",
    "\n",
    "　　上面两条命令均未对视频进行解码，只是将其从一个容器中拷入到另一个容器。\n",
    "\n",
    "# 利用 Caps Filter 过滤码流\n",
    "\n",
    "　　当 Element 包含多个输出 Pad 时，可能导致连接到下一个 Element 的 Pad 具有不确定性。在下一个 Element 支持当前 Element 所有的输出类型，这时 GStreamer 会随机选择一个 Pad 用于连接。  \n",
    "　　例如：我们无法确定下面的 Pipeline 会使用 video\\_00 还是 audio\\_00 连接到 filesink，因为 filesink 同时支持 audio 及 video 输入。\n",
    "\n",
    "```sh\n",
    "$ gst-launch-1.0 souphttpsrc location=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel\\_trailer-480p.webm ! matroskademux ! filesink location=test\n",
    "\n",
    "```\n",
    "\n",
    "　　我们可以如上一节所说，显式指定连接所用的 Pad，或者使用 Caps Filter：\n",
    "\n",
    "```sh\n",
    "$ gst-launch-1.0 souphttpsrc location=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel\\_trailer-480p.webm ! \\\\\n",
    "matroskademux ! video/x-vp8 ! matroskamux ! filesink location=sintel\\_video.mkv\n",
    "```\n",
    "\n",
    "　　Caps Filter 表现为一个只接收指定数据类型的 Element，并将数据传递到下一个 Element，可以高效的解决二义性的问题。  \n",
    "　　我们可以使用 gst-inspect 查看 Element 的输出 Pad，以决定我们的 Caps Filter 需要添加何种参数。在 gst-launch 后加 -v 参数可以输出 Pipeline 连接时所使用的 Pad 信息。  \n",
    "　　对于多个过滤条件，我们需要通过逗号隔开。\n",
    "\n",
    "　　对于某些特殊的类型参数，GStreamer 提供了相应的关键字来进行转换：\n",
    "\n",
    "*   i 或 int 表示整型或范围；\n",
    "*   f 或 float 表示浮点数及范围；\n",
    "*   4 或 fourcc 表示 4 个字符的 FOURCC 代码；\n",
    "*   b, bool, 或 boolean 表示布尔型数据；\n",
    "*   s, str, 或 string 表示字符串；\n",
    "*   fraction 表示分数（例如帧率， 像素宽高比）；\n",
    "*   l 或 list 表示列表。\n",
    "\n",
    "用于发送和接收 UDP RTP 数据：\n",
    "\n",
    "```sh\n",
    "$ gst-launch-1.0 v4l2src ! \\\\\n",
    "video/x-raw-yuv,width=128,height=96,format='(fourcc)'UYVY ! \\\\\n",
    "videoconvert ! ffenc\\_h263 ! video/x-h263 ! rtph263ppay pt=96 ! \\\\\n",
    "udpsink host=192.168.1.1 port=5000 sync=false\n",
    "\n",
    "$gst-launch-1.0 udpsrc port=5000 ! application/x-rtp, \\\\\n",
    "clock-rate=90000,payload=96 ! rtph263pdepay queue-delay=0 ! ffdec\\_h263 \\\\\n",
    "! xvimagesink\n",
    "```\n",
    "\n",
    "　　使用 YUY2 或 YV12 作为测试视频格式，帧率为 30 帧 / 秒：\n",
    "\n",
    "```sh\n",
    "$ gst-launch-1.0 videotestsrc ! \\\\\n",
    "'video/x-raw-yuv,format=(fourcc)YUY2,framerate=30/1;video/x-raw-yuv,format=(fourcc)YV12,framerate=30/1' \\\\\n",
    "! xvimagesink\n",
    "```\n",
    "\n",
    "　　通过 alsasrc 录制文件，限定采样率及位宽：\n",
    "\n",
    "```sh\n",
    "$ gst-launch-1.0 alsasrc! \\\\\n",
    "'audio/x-raw-int,rate=\\[32000,64000\\],width=\\[16,32\\],depth={16,24,32},signed=(boolean)true' \\\\\n",
    "! wavenc ! filesink location=recording.wav\n",
    "```\n",
    "\n",
    "# 总结\n",
    "\n",
    "　　通过本文，我们掌握了：\n",
    "\n",
    "*   如何通过 gst-inspect-1.0 查看当前系统所拥有的 GStreamer 插件以及每个插件的详细信息。\n",
    "*   如何通过 gst-discoverer-1.0 查看媒体文件的 Metadata。\n",
    "*   如何通过 gst-launch-1.0 运行及测试 Pipeline。\n",
    "*   如果通过 Caps Filter 过滤指定数据。\n",
    "\n",
    "# 引用\n",
    "\n",
    "https://gstreamer.freedesktop.org/documentation/tools/gst-launch.html?gi-language=c  \n",
    "https://gstreamer.freedesktop.org/documentation/tutorials/basic/gstreamer-tools.html?gi-language=c\n",
    "\n",
    "作者：[John.Leng](http://www.cnblogs.com/xleng/) 出处：[http://www.cnblogs.com/xleng/](http://www.cnblogs.com/xleng/) 本文版权归作者所有，欢迎转载。商业转载请联系作者获得授权，非商业转载请在文章页面明显位置给出原文连接."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "calc(100% - 180px)",
    "left": "10px",
    "top": "150px",
    "width": "199px"
   },
   "toc_section_display": true,
   "toc_window_display": true
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
